package com.have.blog.web.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.have.blog.base.enums.BlogStatus;
import com.have.blog.base.wrapper.CommonPage;
import com.have.blog.base.wrapper.Wrapper;
import com.have.blog.config.hloder.RequestHolder;
import com.have.blog.model.mapper.BlogMapper;
import com.have.blog.model.mapper.CommentReportMapper;
import com.have.blog.model.mapper.UserCommentMapper;
import com.have.blog.model.mapper.UserMapper;
import com.have.blog.model.models.*;
import com.have.blog.picture.service.PictureFeignApi;
import com.have.blog.utils.MyBeanUtils;
import com.have.blog.web.constant.BlogConstant;
import com.have.blog.web.dao.UserDao;
import com.have.blog.web.dto.BlogDto;
import com.have.blog.web.dto.CommentDto;
import com.have.blog.web.dto.UserDto;
import com.have.blog.web.dto.WebConfigDto;
import com.have.blog.web.service.CommentService;
import com.have.blog.web.service.UserService;
import com.have.blog.web.service.WebConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
@SuppressWarnings("all")
public class CommentServiceImpl implements CommentService {

    @Autowired
    private UserCommentMapper commentMapper;
    @Autowired
    private PictureFeignApi pictureFeignApi;
    @Autowired
    private WebConfigService webConfigService;
    @Autowired
    private BlogMapper blogMapper;
    @Autowired
    private CommentReportMapper reportMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserDao userDao;



    @Override
    public Wrapper<CommonPage<CommentDto>> getPageList(String source, Integer blogUid, Integer pageNum, Integer pageSize) {
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        UserCommentExample commentExample = new UserCommentExample();
        UserCommentExample.Criteria criteria = commentExample.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        if (!StringUtils.isEmpty(source)) {
            criteria.andSourceEqualTo(source);
        }
        if (!StringUtils.isEmpty(blogUid)) {
            criteria.andBlogUidEqualTo(blogUid);
        }
        criteria.andFirstCommentUidIsNull(); // 查询一级标题
        commentExample.setOrderByClause("create_time desc");
        List<UserComment> firstCommentList = commentMapper.selectByExample(commentExample);
        long total = page.getTotal();
        int currentPageNum = page.getPageNum();
        if (CollectionUtils.isEmpty(firstCommentList)) {
            return Wrapper.success(CommonPage.restPage(new ArrayList<>()));
        }

        List<Integer> firstCommentUids = new ArrayList<>();
        firstCommentList.forEach(item -> { // 获得所有一级评论
            if (item.getToCommentUid() == null) {
                firstCommentUids.add(item.getUid());
            }
        });

        // 查询子评论
        commentExample.clear();
        commentExample.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andFirstCommentUidIn(firstCommentUids);
        List<UserComment> subCommentList = commentMapper.selectByExample(commentExample);
        List<UserComment> allComments = new ArrayList<>();
        allComments.addAll(firstCommentList);
        allComments.addAll(subCommentList);
        Set<Integer> set = new HashSet<>();
        for (UserComment item : allComments) {
            if (item.getUserUid() != null) {
                set.add(item.getUserUid());
            }
            if (item.getToUserUid()!=null) {
                set.add(item.getToUserUid());
            }
        }

        Map<Integer, UserDto> userMap = userService.getUserByUids(new ArrayList<>(set));
        List<CommentDto> commentDtos = MyBeanUtils.copyListProperties(allComments, CommentDto::new);
        List<CommentDto> resultList = setSubComment(commentDtos);
        for (CommentDto commentDto : commentDtos) {
            commentDto.setUser(userMap.get(commentDto.getUserUid()));
            commentDto.setToUser(userMap.get(commentDto.getToUserUid()));
        }
        CommonPage<CommentDto> commonPage = CommonPage.restPage(resultList);
        commonPage.setTotal(page.getTotal());
        commonPage.setPageNum(page.getPageNum());
        return Wrapper.success(commonPage);
    }

    public List<CommentDto> setSubComment(List<CommentDto> commentDtoList) {
        List<CommentDto> firstCommentList = new ArrayList<>();
        Map<Integer, List<CommentDto>> toUidMap = new HashMap<>();
        for (CommentDto item : commentDtoList) {
            if (item.getFirstCommentUid() == null) {
                firstCommentList.add(item);
                continue;
            }
            List<CommentDto> tempList = toUidMap.get(item.getToCommentUid());
            if (CollectionUtils.isEmpty(tempList)) {
                tempList = new ArrayList<>();
                toUidMap.put(item.getToCommentUid(), tempList);
            }
            tempList.add(item);
        }
        for (CommentDto item : commentDtoList) {
            item.setReplyList(toUidMap.get(item.getUid()));
        }
        return firstCommentList;
    }

    public void setCommentUser(List<CommentDto> commentDtoList) {
        // 查询评论用户
        Set<Integer> userUidSet = new HashSet<>();
        commentDtoList.forEach(item ->{
            if (item.getUserUid() != null) {
                userUidSet.add(item.getUserUid());
            }
            if (item.getToUserUid() != null) {
                userUidSet.add(item.getToUserUid());
            }
        });
        Map<Integer, UserDto> userDtoMap = userService.getUserByUids(new ArrayList<>(userUidSet));
        for (CommentDto comment : commentDtoList) {
            comment.setUser(userDtoMap.get(comment.getUserUid()));
            comment.setToUser(userDtoMap.get(comment.getToUserUid()));
        }
    }

    @Override
    public Wrapper getCommentByUser(Integer pageNum, Integer pageSize) {
        Integer userUid = RequestHolder.getUserUid();
        if (userUid == null) {
            return Wrapper.unauthorized();
        }
        // 获取用户评论
        PageHelper.startPage(pageNum, pageSize);
        UserCommentExample example = new UserCommentExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andTypeEqualTo(0)
                .andUserUidEqualTo(userUid);
        example.setOrderByClause("create_time");
        List<UserComment> releaseComments = commentMapper.selectByExample(example);

        // 获取用户受到评论
        PageHelper.startPage(pageNum, pageSize);
        example.clear();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andTypeEqualTo(0)
                .andToUserUidEqualTo(userUid);
        example.setOrderByClause("create_time desc");
        List<UserComment> receiveComments = commentMapper.selectByExample(example);
        List<CommentDto> commentList = MyBeanUtils.copyListProperties(releaseComments, CommentDto::new);
        List<CommentDto> replyCommentList = MyBeanUtils.copyListProperties(receiveComments, CommentDto::new);
        setCommentUser(commentList);
        setCommentUser(replyCommentList);

        Set<Integer> blogUids = new HashSet<>();
        commentList.forEach(item -> { if(item.getBlogUid() != null) blogUids.add(item.getBlogUid());});
        replyCommentList.forEach(item -> { if(item.getBlogUid() != null) blogUids.add(item.getBlogUid());});
        BlogExample blogExample = new BlogExample();
        blogExample.createCriteria().andUidIn(new ArrayList<>(blogUids));
        List<Blog> blogList = blogMapper.selectByExample(blogExample);
        List<BlogDto> blogDtos = MyBeanUtils.copyListProperties(blogList, BlogDto::new);
        Map<Integer, BlogDto> blogMap = new HashMap<>();
        for (BlogDto blogDto : blogDtos) {
            blogMap.put(blogDto.getUid(), blogDto);
        }
        for (CommentDto commentDto : commentList) {
            commentDto.setBlog(blogMap.get(commentDto.getBlogUid()));
        }
        for (CommentDto commentDto : replyCommentList) {
            commentDto.setBlog(blogMap.get(commentDto.getBlogUid()));
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("commentList", commentList);
        resultMap.put("replyList", replyCommentList);
        return Wrapper.success(resultMap);
    }

    @Override
    public Wrapper getPraiseListByUser(Integer pageNum, Integer pageSize) {
        Integer userUid = RequestHolder.getUserUid();
        if (userUid == null) {
            return Wrapper.unauthorized();
        }
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        UserCommentExample example = new UserCommentExample();
        example.createCriteria()
                .andUserUidEqualTo(userUid)
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andTypeEqualTo(1);
        example.setOrderByClause("create_time desc");
        List<UserComment> commentList = commentMapper.selectByExample(example);
        long total = page.getTotal();
        pageNum = page.getPageNum();
        List<CommentDto> commentDtos = MyBeanUtils.copyListProperties(commentList, CommentDto::new);
        List<Integer> blogUid = new ArrayList<>();
        commentList.forEach(item -> {
            if (item.getBlogUid() != null) {
                blogUid.add(item.getBlogUid());
            }
        });
        if (!CollectionUtils.isEmpty(blogUid)) {
            BlogExample blogExample = new BlogExample();
            blogExample.createCriteria()
                    .andUidIn(blogUid);
            List<Blog> blogs = blogMapper.selectByExample(blogExample);
            List<BlogDto> blogDtos = MyBeanUtils.copyListProperties(blogs, BlogDto::new);
            Map<Integer, BlogDto> blogMap = new HashMap<>();
            for (BlogDto blogDto : blogDtos) {
                blogMap.put(blogDto.getUid(), blogDto);
            }
            commentDtos.forEach(item -> {
                item.setBlog(blogMap.get(item.getBlogUid()));
            });
        }
        CommonPage<CommentDto> commonPage = CommonPage.restPage(commentDtos);
        commonPage.setTotal(total);
        commonPage.setPageNum(pageNum);
        return Wrapper.success(commonPage);
    }

    @Transactional
    @Override
    public Wrapper addComment(CommentDto commentDto) {
        if (StringUtils.isEmpty(commentDto.getContent())) {
            return Wrapper.failed("评论不能为空");
        }
        WebConfigDto webConfig = webConfigService.getWebConfig();
        if (BlogConstant.CAN_NOT_COMMENT.equals(webConfig.getOpenComment())) {
            return Wrapper.failed("BLOG CANNOT COMMENT!");
        }
        Integer userUid = RequestHolder.getUserUid();
        User tUser = userMapper.selectByPrimaryKey(userUid);
        if (tUser == null) {
            return Wrapper.failed("请先登录");
        }
        if (tUser.getCommentStatus() == 0) {
            return Wrapper.failed("您已被禁言");
        }
        BlogExample example = new BlogExample();
        if (!StringUtils.isEmpty(commentDto.getBlogUid())) {
            example.createCriteria().andUidEqualTo(commentDto.getBlogUid());
            List<Blog> blogs = blogMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(blogs)) {
                return Wrapper.failed("博客不存在");
            }
            Blog blog = blogs.get(0);
            if (BlogConstant.CAN_NOT_COMMENT.equals(blog.getOpenComment())) {
                return Wrapper.failed("BLOG CAN NOT COMMENT!");
            }
        }

        UserComment comment = new UserComment();
        MyBeanUtils.copyProperties(commentDto, comment);
        comment.setStatus(BlogStatus.ENABLE.getStatus());
        comment.setType(0);
        comment.setUserUid(userUid);
        commentMapper.insert(comment);
        MyBeanUtils.copyProperties(comment, commentDto);
        return Wrapper.success(commentDto);
    }

    /**
     * 需要递归删除
     * @param commentDto
     * @return
     */
    @Override
    public Wrapper deleteComments(CommentDto commentDto) {
        Integer userUid = RequestHolder.getUserUid();
        UserComment comment = commentMapper.selectByPrimaryKey(commentDto.getUid());
        if (!comment.getUserUid().equals(userUid)) {
            return Wrapper.forbidden();
        }
        UserCommentExample example = new UserCommentExample();
        if (StringUtils.isEmpty(comment.getToCommentUid())) {
            example.createCriteria()
                    .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                    .andToCommentUidEqualTo(comment.getUid());
        } else {
            example.createCriteria()
                    .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                    .andUidEqualTo(comment.getUid());
        }
        List<UserComment> commentList = commentMapper.selectByExample(example);
        commentList.add(comment);
        List<Integer> uids = new ArrayList<>();
        commentList.forEach(item -> {
            uids.add(item.getUid());
        });

        example.clear();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andUidIn(uids);
        UserComment template = new UserComment();
        template.setStatus(BlogStatus.DISABLE.getStatus());
        int result = commentMapper.updateByExampleSelective(template, example);
        if (result > 0) {
            return Wrapper.success();
        }
        return Wrapper.failed();
    }

    @Transactional
    @Override
    public Wrapper reportComment(CommentDto commentDto) {
        UserComment comment = commentMapper.selectByPrimaryKey(commentDto.getUid());
        if (BlogStatus.DISABLE.getStatus() == comment.getStatus()) {
            return Wrapper.successWithMessage("文章已被处理");
        }
        HttpServletRequest request = RequestHolder.getRequest();
        String userUid = request.getAttribute(BlogConstant.USER_UID).toString();
        if (comment.getUserUid().equals(userUid)) {
            return Wrapper.failed("举报自己！真是个狠人");
        }
        CommentReportExample example = new CommentReportExample();
        example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andReportedCommentUidEqualTo(comment.getUid())
                .andUserUidEqualTo(commentDto.getUserUid());
        long count = reportMapper.countByExample(example);
        if (count > 0) {
            return Wrapper.failed("请不要重复举报");
        }
        CommentReport tCommentReport = new CommentReport();
        tCommentReport.setContent(commentDto.getContent());
        tCommentReport.setStatus(BlogStatus.ENABLE.getStatus());
        tCommentReport.setProgress(0);
        tCommentReport.setUserUid(commentDto.getUserUid());
        tCommentReport.setReportedCommentUid(commentDto.getUid());
        tCommentReport.setReportedUserUid(comment.getUserUid());
        int result = reportMapper.insert(tCommentReport);
        if (result > 0) {
            return Wrapper.success();
        }
        return Wrapper.failed();
    }
}
